﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using HYRevitCode.TransformUtility;

namespace HYRevitCode.ElementSearchUtility.LinkDocumentSuite
{
	internal class ViewTransformFilterBean : BaseTransformFilterClass
	{
		internal bool IfViewLimit
		{
			get
			{
				return this.m_bIfViewLimit;
			}
			private set
			{
				this.m_bIfViewLimit = value;
			}
		}

		internal ViewTransformFilterBean(List<ElementFilterPacker> input, Transform inputTransform, CustomGetElementFilter inputDelegate = null) : base(inputTransform)
		{
			if (input != null)
			{
				this.m_lstAllFilter = input;
			}
			else
			{
				this.m_lstAllFilter = new List<ElementFilterPacker>();
			}
			if ((from n in this.m_lstAllFilter
			where n.IsNeedTransform
			select n).Count<ElementFilterPacker>() > 0 || this.m_GetElementFilterDelegate != null)
			{
				this.IfViewLimit = true;
			}
			this.m_useTransform = inputTransform;
		}

		internal ViewTransformFilterBean AddTransform(Transform input)
		{
			List<ElementFilterPacker> list = new List<ElementFilterPacker>();
			list.AddRange(this.m_lstAllFilter);
			Transform addTransform = base.GetAddTransform(input);
			return new ViewTransformFilterBean(list, addTransform, this.m_GetElementFilterDelegate);
		}

		internal override ElementFilter GetUseFilter()
		{
			List<ElementFilter> list = new List<ElementFilter>();
			ElementFilter elementFilter = null;
			foreach (ElementFilterPacker elementFilterPacker in this.m_lstAllFilter)
			{
				if (elementFilterPacker.ThisElementFilter != null)
				{
					ElementFilter elementFilter2 = null;
					if (elementFilterPacker.IsNeedTransform && elementFilterPacker.ThisElementFilter is BoundingBoxContainsPointFilter)
					{
						elementFilter2 = this.GetABoundingBoxContainsPointFilter(elementFilterPacker.ThisElementFilter);
					}
					else if (elementFilterPacker.IsNeedTransform && elementFilterPacker.ThisElementFilter is BoundingBoxIntersectsFilter)
					{
						elementFilter2 = this.GetABoundingBoxIntersectsFilter(elementFilterPacker.ThisElementFilter);
					}
					else if (elementFilterPacker.IsNeedTransform && elementFilterPacker.ThisElementFilter is BoundingBoxIsInsideFilter)
					{
						elementFilter2 = this.GetABoundingBoxIsInsideFilter(elementFilterPacker.ThisElementFilter);
					}
					else if (elementFilterPacker.IsNeedTransform && elementFilterPacker.ThisElementFilter is ElementIntersectsSolidFilter)
					{
						elementFilter2 = this.GetAElementIntersectionSolidFilter(elementFilterPacker.ThisElementFilter);
					}
					else if (elementFilterPacker.IsNeedTransform && elementFilterPacker.ThisElementFilter is ElementOwnerViewFilter)
					{
						if (this.m_useTransform == null)
						{
							list.Add(elementFilterPacker.ThisElementFilter);
						}
					}
					else
					{
						list.Add(elementFilterPacker.ThisElementFilter);
					}
					if (elementFilter2 != null)
					{
						if (elementFilter == null)
						{
							elementFilter = elementFilter2;
						}
						else
						{
							elementFilter = new LogicalOrFilter(elementFilter, elementFilter2);
						}
					}
				}
			}
			if (elementFilter != null)
			{
				list.Add(elementFilter);
			}
			if (this.m_GetElementFilterDelegate != null)
			{
				ElementFilter elementFilter3 = this.m_GetElementFilterDelegate(this.m_useTransform);
				if (elementFilter3 != null)
				{
					list.Add(elementFilter3);
				}
			}
			return new LogicalAndFilter(list);
		}

		private ElementFilter GetABoundingBoxIsInsideFilter(ElementFilter oneFilter)
		{
			ElementFilter result;
			if (this.m_useTransform != null)
			{
				Outline outline = (oneFilter as BoundingBoxIsInsideFilter).GetBoundingBox();
				XYZ xyz;
				XYZ xyz2;
				outline = this.GetATransFormedOutline(out xyz, out xyz2, outline);
				double tolerance = (oneFilter as BoundingBoxIsInsideFilter).Tolerance;
				bool inverted = (oneFilter as BoundingBoxIsInsideFilter).Inverted;
				result = new BoundingBoxIsInsideFilter(outline, tolerance, inverted);
			}
			else
			{
				result = oneFilter;
			}
			return result;
		}

		private ElementFilter GetABoundingBoxIntersectsFilter(ElementFilter oneFilter)
		{
			ElementFilter result;
			if (this.m_useTransform != null)
			{
				Outline outline = (oneFilter as BoundingBoxIntersectsFilter).GetBoundingBox();
				XYZ xyz;
				XYZ xyz2;
				outline = this.GetATransFormedOutline(out xyz, out xyz2, outline);
				double tolerance = (oneFilter as BoundingBoxIntersectsFilter).Tolerance;
				bool inverted = (oneFilter as BoundingBoxIntersectsFilter).Inverted;
				result = new BoundingBoxIntersectsFilter(outline, tolerance, inverted);
			}
			else
			{
				result = oneFilter;
			}
			return result;
		}

		private ElementFilter GetABoundingBoxContainsPointFilter(ElementFilter oneFilter)
		{
			ElementFilter result;
			if (this.m_useTransform != null)
			{
				XYZ point = (oneFilter as BoundingBoxContainsPointFilter).Point;
				double tolerance = (oneFilter as BoundingBoxContainsPointFilter).Tolerance;
				bool inverted = (oneFilter as BoundingBoxContainsPointFilter).Inverted;
				result = new BoundingBoxContainsPointFilter(TransformUtilityMethod.TransformPoint(point, this.m_useTransform), tolerance, inverted);
			}
			else
			{
				result = oneFilter;
			}
			return result;
		}

		private ElementFilter GetAElementIntersectionSolidFilter(ElementFilter oneFilter)
		{
			ElementFilter result;
			if (this.m_useTransform != null)
			{
				Solid solid = (oneFilter as ElementIntersectsSolidFilter).GetSolid();
				if (null == solid)
				{
					return oneFilter;
				}
				bool inverted = (oneFilter as ElementIntersectsSolidFilter).Inverted;
				solid = TransformUtilityMethod.TransformSolid(solid, this.m_useTransform);
				result = new ElementIntersectsSolidFilter(solid, inverted);
			}
			else
			{
				result = oneFilter;
			}
			return result;
		}

		private Outline GetATransFormedOutline(out XYZ tempPointOne, out XYZ tempPointTwo, Outline tempOutline)
		{
			tempPointOne = TransformUtilityMethod.TransformPoint(tempOutline.MaximumPoint, this.m_useTransform);
			tempPointTwo = TransformUtilityMethod.TransformPoint(tempOutline.MinimumPoint, this.m_useTransform);
			tempOutline = new Outline(tempPointTwo, tempPointOne);
			return tempOutline;
		}

		private List<ElementFilterPacker> m_lstAllFilter = new List<ElementFilterPacker>();

		private bool m_bIfViewLimit;

		private CustomGetElementFilter m_GetElementFilterDelegate;
	}
}
